/* eslint-disable indent */
import React, { FC, useEffect } from 'react';
import { Graph, Addon, Shape } from '@antv/x6';
import '@antv/x6-react-shape';
import MyComponent from './MyComponent';

let graph: Graph;
const AntV_X6_Dnd: FC = () => {
  useEffect(() => {
    Custom_Node();
    create();
    return () => {
      graph.dispose();
    };
  }, []);
  const Custom_Node = () => {
    // 注册 React 组件
    Graph.registerReactComponent(
      'my-component-rect',
      (node) => {
        const data = node.getData();
        return <MyComponent name={data.name} message={data.message} />;
      },
      true
    );
  };

  const data = {
    nodes: [
      {
        id: 'node1',
        shape: 'rect', // 使用 rect 渲染
        x: 100,
        y: 200,
        width: 200,
        height: 100,
        label: 'hello',
      },
      {
        id: 'node2',
        shape: 'ellipse', // 使用 ellipse 渲染
        x: 300,
        y: 200,
        width: 80,
        height: 40,
        label: 'world',
      },
    ],
    edges: [
      {
        source: 'node1',
        target: 'node2',
        router: {
          name: 'er',
          args: {
            offset: 'center',
          },
        },
      },
    ],
  };
  const create = () => {
    const main = document.getElementById('main');

    graph = new Graph({
      container: main || undefined,
      width: 800,
      height: 600,
      background: {
        color: '#fff', // 设置画布背景颜色
      },
      grid: {
        size: 10, // 网格大小 10px
        visible: true, // 渲染网格背景
      },
      scroller: false, // 滚动
      panning: {
        // 画布平移
        enabled: true, // 启用画布平移
        modifiers: 'shift', // 需要按下修饰键,方可平移
      },
      // // 连线规则
      // connecting: {
      //   snap: true,
      //   allowBlank: false,
      //   allowLoop: false,
      //   allowMulti: false,
      //   router: {
      //     name: 'er',
      //     args: {
      //       offset: 'center',
      //     },
      //   },
      //   validateConnection({ sourceCell, targetCell }) {
      //     if (targetCell?.id === 'node1') {
      //       return false;
      //     }
      //     return true;
      //   },
      // },
      mousewheel: {
        enabled: true,
        zoomAtMousePosition: true,
        modifiers: 'ctrl',
        minScale: 0.5,
        maxScale: 3,
      },
      connecting: {
        router: 'manhattan',
        connector: {
          name: 'rounded',
          args: {
            radius: 8,
          },
        },
        allowLoop: false,
        allowMulti: false,
        allowPort: false,
        anchor: {
          name: 'center',
        },
        allowBlank: false,
        snap: {
          radius: 20,
        },
        createEdge() {
          return new Shape.Edge({
            attrs: {
              line: {
                stroke: '#A2B1C3',
                strokeWidth: 2,
                targetMarker: {
                  name: 'block',
                  width: 12,
                  height: 8,
                },
              },
            },
            zIndex: 0,
          });
        },
      },
      resizing: true, // 缩放节点
      rotating: true, // 旋转节点，
      // 点选/框选
      selecting: {
        enabled: true,
        rubberband: true,
        showNodeSelectionBox: true,
      },
      snapline: true, // 对齐线
      embedding: {
        enabled: true,
        findParent({ node }) {
          const bbox = node.getBBox();
          return this.getNodes().filter((node) => {
            const data = node.getData<any>();
            if (data && data.parent) {
              const targetBBox = node.getBBox();
              return bbox.isIntersectWithRect(targetBBox);
            }
            return false;
          });
        },
      },
    });
    graph.fromJSON(data);
    graph.addNode({
      x: 40,
      y: 40,
      width: 100,
      height: 100,
      shape: 'react-shape',
      component: 'my-component-rect',
      visible: true, // 是否可见
      data: {
        name: 'Hello',
        message: 'Word',
      },
      ports: {
        groups: {
          group1: {
            attrs: {
              circle: {
                r: 6,
                magnet: true,
                stroke: '#31d0c6',
                strokeWidth: 2,
                fill: '#fff',
              },
            },
            position: {
              name: 'left',
              args: {},
            },
          },
        },
        items: [
          {
            id: 'port1',
            group: 'group1', // 指定分组名称
          },
        ],
      },
    });
    graph.centerContent(); // 将画布内容中心与视口中心对齐
    graph.on('edge:connected', ({ isNew, edge }) => {
      if (isNew) {
        // 对新创建的边进行插入数据库等持久化操作
      }
    });

    graph.on('node:added', ({ node, index, options }) => {
      if (node.getData().parent) {
        node.setZIndex(0);
      }
    });

    graph.on('cell:dblclick', ({ cell, e }) => {
      const isNode = cell.isNode();
      const name = cell.isNode() ? 'node-editor' : 'edge-editor';

      cell.removeTool(name);
      cell.addTools({
        name,
        args: {
          event: e,
          attrs: {
            backgroundColor: isNode ? '#EFF4FF' : '#FFF',
          },
        },
      });
    });
  };
  const onMouseDown = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    // dnd
    const dnd = new Addon.Dnd({
      target: graph,
      animation: true,
      validateNode(droppingNode, options) {
        return true;
      },
    });

    const target = e.currentTarget;
    const type = target.getAttribute('data-type'); // 获取该dom上的 data-type 属性
    const data = target.getAttribute('data-data') || JSON.stringify({});

    const node =
      type === 'rect'
        ? graph.createNode({
            width: 100,
            height: 100,
            shape: 'react-shape',
            component: 'my-component-rect',
            visible: true, // 是否可见
            data: {
              name: 'Rect',
              message: 'rect',
            },
            ports: {
              groups: {
                group1: {
                  attrs: {
                    circle: {
                      r: 6,
                      magnet: true,
                      stroke: '#31d0c6',
                      strokeWidth: 2,
                      fill: '#fff',
                    },
                  },
                  position: {
                    name: 'left',
                    args: {},
                  },
                },
              },
              items: [
                {
                  id: 'port1',
                  group: 'group1', // 指定分组名称
                },
              ],
            },
          })
        : graph.createNode({
            width: 200,
            height: 200,
            shape: type || '',
            attrs: {},
            ports: {
              groups: {
                group1: {
                  attrs: {
                    circle: {
                      r: 6,
                      magnet: true,
                      stroke: '#31d0c6',
                      strokeWidth: 2,
                      fill: '#fff',
                    },
                  },
                  position: {
                    name: 'left',
                    args: {},
                  },
                },
              },
              items: [
                {
                  id: 'port1',
                  group: 'group1', // 指定分组名称
                },
              ],
            },
            data: JSON.parse(data),
          });

    if (!node) return;
    dnd.start(node, e.nativeEvent);
  };

  return (
    <div className="app">
      <div className="dnd-wrap">
        <div data-type="rect" className="dnd-rect" onMouseDown={onMouseDown}>
          Rect
        </div>
        <div
          data-type="circle"
          className="dnd-circle"
          onMouseDown={onMouseDown}
        >
          Circle
        </div>
        <div
          data-type="circle"
          className="dnd-ParentCircle"
          onMouseDown={onMouseDown}
          data-data={JSON.stringify({
            parent: true,
          })}
        >
          ParentCircle
        </div>
      </div>
      <div className="app-content" id="main" />
    </div>
  );
};

export default AntV_X6_Dnd;
